package com.define.ssh.dao.impl;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;

import org.hibernate.impl.CriteriaImpl.OrderEntry;
import org.hibernate.transform.AliasToEntityMapResultTransformer;
import org.springframework.util.Assert;

import com.define.ssh.dao.BasicIDao;
import com.define.ssh.util.HibernateUtil;
import com.define.ssh.util.PageSupport;

public class BasicDao implements BasicIDao {
	private SessionFactory sessionFactory;

	@Override
	@Resource(name = "sessionFactory")
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	@Override
	public Session getSession() {
		return sessionFactory.getCurrentSession();
	}

	public Session getNewSession() {
		return sessionFactory.openSession();
	}

	/**
	 * 保存对象 新增
	 * 
	 * @param entity
	 * 
	 */
	@Override
	public void save(final Object entity) {
		this.getSession().save(entity);
	}

	/**
	 * 新增或更新对象
	 * 
	 * @param entity
	 */
	@Override
	public void saveOrupdate(final Object entity) {
		this.getSession().saveOrUpdate(entity);
	}

	/**
	 * 更新对象
	 * 
	 * @param entity
	 */
	@Override
	public void update(final Object entity) {
		this.getSession().update(entity);
	}

	/**
	 * 删除对象
	 * 
	 * @param entity
	 */
	@Override
	public void delete(final Object entity) {
		this.getSession().delete(entity);
	}

	/**
	 * TODO 批量删除
	 * 
	 * @param hql
	 * @param hql
	 * @return int
	 */
	public int deletes(final String hql, final Object[] ids) {

		final Query query = this.getSession().createQuery(hql);
		query.setParameterList("ids", ids);
		return query.executeUpdate();

	}

	/**
	 * 根据ID获取对象
	 * 
	 * @param entity
	 * @param id
	 * @return 对象，或者未能发现符合条件的记录，返回null
	 */

	@Override
	public <T> T get(final Class<T> clazz, Serializable id) {
		return (T) this.getSession().get(clazz, id);
	}

	/**
	 * 返回所有对象的列表
	 * 
	 * @param entity
	 * @return
	 */
	@Override
	public List findAll(final Class entity) {
		return this.getSession().createQuery("from " + entity.getName()).list();
	}

	/**
	 * 
	 * @param query
	 * @return list
	 */
	@Override
	public List findByQuery(final String query) {
		return this.getSession().createQuery(query).list();
	}

	/**
	 * 
	 * @param query
	 * @param parameter
	 * @return list
	 */
	@Override
	public List findByQuery(final String querySql, final Object parameter) {
		final Query query = this.getSession().createQuery(querySql);
		query.setParameter(0, parameter);
		return query.list();
	}

	/**
	 * @param query
	 * @param parameter
	 * @return
	 */
	@Override
	public List findByQuery(final String querySql, final Object[] parameter) {
		final Query query = this.getSession().createQuery(querySql);
		for (int i = 0; i < parameter.length; i++) {
			query.setParameter(i, parameter[i]);
		}
		return query.list();
	}

	/**
	 * 创建Query
	 * 
	 * @param queryString
	 * @param values
	 * @return
	 */
	@Override
	public Query createQuery(String queryString, Object[] values)
	/*     */{
		/* 135 */Assert.hasText(queryString);
		/* 136 */final Query queryObject = this.getSession().createQuery(
				queryString);
		/* 137 */if (values != null) {
			/* 138 */for (int i = 0; i < values.length; ++i) {
				/* 139 */queryObject.setParameter(i, values[i]);
				/*     */}
			/*     */}
		/* 142 */return queryObject;
		/*     */}

	/**
	 * sql语句查询
	 * 
	 * @param sql
	 * @return
	 */

	@Override
	public List findBySqlQuery(final String sql) {
		final SQLQuery query = this.getSession().createSQLQuery(sql);
		return query.list();
	}

	/**
	 * 创建SQLQuery
	 * 
	 * @param queryString
	 * @param values
	 * @return
	 */
	@Override
	public SQLQuery createSQLQuery(String queryString, Object[] values)
	/*     */{
		/* 169 */Assert.hasText(queryString);
		/* 170 */final SQLQuery queryObject = this.getSession().createSQLQuery(
				queryString);
		/* 171 */if (values != null) {
			/* 172 */for (int i = 0; i < values.length; ++i) {
				/* 173 */queryObject.setParameter(i, values[i]);
				/*     */}
			/*     */}
		/* 176 */return queryObject;
		/*     */}

	/**
	 * 执行sql返回map
	 * 
	 * @param queryString
	 * @param values
	 * @return
	 */
	@Override
	public List<Map<Object, Object>> doSQLQuery(String queryString,
			Object... values) {
		return this
				.createSQLQuery(queryString, values)
				.setResultTransformer(
						AliasToEntityMapResultTransformer.INSTANCE).list();
	}

	@Override
	public Object getSqlObject(final String sql) {
		final Object object = this.getSession().createSQLQuery(sql)
				.uniqueResult();
		return object;
	}

	/**
	 * sql语句分页查询
	 * 
	 * @param sql
	 * @param pageSize
	 * @param pageNo
	 * @return
	 */
	@Override
	public List findBySqlQueryOnPage(final String sql, final int pageSize,
			final int pageNo) {
		int startIndex = pageSize * (pageNo - 1);
		if (pageNo == 0) {
			startIndex = 0;
		}
		final int startIndex1 = startIndex;
		final Query queryObject = this.getSession().createSQLQuery(sql);
		queryObject.setFirstResult(startIndex1);
		queryObject.setMaxResults(pageSize);

		return queryObject.list();
	}

	/**
	 * 
	 * 查询指定数量的对象 带分页条件
	 * 
	 * @param query
	 * @param parameter
	 * @return
	 */
	@Override
	public List findObjectListByPage(final String hql,
			final Object[] parameter, final int pageNo, final int pageSize) {
		final int startIndex = pageSize * (pageNo - 1);

		final Query query = this.getSession().createSQLQuery(hql);
		query.setFirstResult(startIndex);
		query.setMaxResults(pageSize);
		if (parameter != null) {
			for (int i = 0; i < parameter.length; i++) {
				query.setParameter(i, parameter[i]);
			}
		}
		final List list = query.list();
		return list;

	}

	/**
	 * 
	 * 查询满足条件的数量
	 * 
	 * @param query
	 * @param parameter
	 * @return
	 */
	@Override
	public int findCountByCondition(final String hql, final Object[] parameter) {

		final Query query = this.getSession().createSQLQuery(hql);
		if (parameter != null) {
			for (int i = 0; i < parameter.length; i++) {
				query.setParameter(i, parameter[i]);
			}
		}
		final Object object = query.uniqueResult();
		if (object == null) {
			return 0;
		}
		return Integer.parseInt("" + object.toString());

	}

	/**
	 * 
	 * 查询指定数量的对象
	 * 
	 * @param query
	 * @param parameter
	 * @return
	 */
	@Override
	public List findNumList(final String query, final int resultcount) {
		final Session session = this.getSession();
		final Query q = session.createQuery(query);
		q.setMaxResults(resultcount);
		return q.list();
	}

	/**
	 * 返回符合条件的记录列表
	 * 
	 * @param dc
	 * @return list
	 */
	@Override
	public List findByCriteria(final DetachedCriteria dc) {
		final Session session = this.getSession();
		final Criteria criteria = dc.getExecutableCriteria(session);
		criteria.setProjection(null);
		criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
		return criteria.list();
	}

	/**
	 * 搜索指定数量的数据
	 * 
	 * @param dc
	 * @param count
	 * @return
	 */
	@Override
	public List findByCriteria(final DetachedCriteria dc, final int count) {
		final Session session = this.getSession();
		final Criteria criteria = dc.getExecutableCriteria(session);
		// criteria.setProjection(null);
		criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY)
				.setMaxResults(count);
		return criteria.list();

	}

	/**
	 * 
	 * @param hql
	 * @param values
	 * @return
	 */
	@Override
	public int execute(final String hql, final Object[] values) {
		final Session session = this.getSession();
		final Query queryObject = session.createQuery(hql);
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				queryObject.setParameter(i, values[i]);
			}
		}
		final int i = queryObject.executeUpdate();
		return new Integer(i);

	}

	/**
	 * 执行hql 更新,删除 操作
	 * 
	 * @param hql
	 * @return int
	 */
	@Override
	public int execute(final String hql) {
		final Session session = this.getSession();
		final Query queryObject = session.createQuery(hql);
		final int i = queryObject.executeUpdate();
		return new Integer(i);

	}

	/**
	 * 执行sql 更新,删除 操作
	 * 
	 * @param sql
	 * @return
	 */
	@Override
	public int executeSql(final String sql) {
		final Session session = this.getSession();
		final Query queryObject = session.createSQLQuery(sql);
		final int i = queryObject.executeUpdate();
		return new Integer(i);

	}

	/**
	 * 
	 * @Description: TODO
	 * @param sql
	 * @param values
	 * @return
	 */
	@Override
	public int executeSql(final String sql, final Object[] values) {
		final Session session = this.getSession();
		final Query queryObject = session.createSQLQuery(sql);
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				queryObject.setParameter(i, values[i]);
			}
		}
		final int i = queryObject.executeUpdate();
		return new Integer(i);

	}

	/**
	 * 仅支持以 select count(*) from ... *
	 * 
	 * @param sql
	 * @return
	 * @author agu
	 */
	@Override
	public long findCountBySql(final String sql) {
		final Session session = this.getSession();
		final List temp = session.createSQLQuery(sql).list();
		if (temp != null && temp.size() == 1) {
			final Object o = temp.get(0);
			if (o == null) {
				return 0l;
			} else {
				if (o instanceof java.math.BigDecimal) {

					final java.math.BigDecimal count = (java.math.BigDecimal) o;
					return count.longValue();

				} else {
					final java.math.BigInteger count = (java.math.BigInteger) o;

					return count.longValue();
				}
			}
		} else {
			return new Long(0);
		}

	}

	/**
	 * hql
	 * 
	 * @param hql
	 * @return
	 */
	@Override
	public int findCountByQuery(final String hql) {
		final Session session = this.getSession();
		final Query queryObject = session.createQuery(hql);
		final Object obj = queryObject.uniqueResult();
		return Integer.parseInt(obj.toString());

	}

	/**
	 * 分页查询
	 * 
	 * @param dc
	 * @param pageSize
	 * @param pageNo
	 *            从1开始的页数
	 * @return PaginationSupport
	 * @throws ServiceException
	 */
	@Override
	public PageSupport findPageOnPageNo(final DetachedCriteria dc,
			final int pageSize, final int pageNo) {
		return this.findPageByCriteria(dc, pageSize, pageNo);

	}

	/**
	 * 分页查询
	 * 
	 * @param dc
	 *            条件
	 * @param page
	 *            页面信息 包含 maxperpage pagenumber 等
	 */

	@Override
	public PageSupport findPageOnPageNo(final DetachedCriteria dc,
			final PageSupport page) {
		final Session session = this.getSession();
		final Criteria criteria = dc.getExecutableCriteria(session);
		final long recordCount = ((Long) criteria.setProjection(
				Projections.rowCount()).uniqueResult()).longValue();
		criteria.setProjection(null);
		criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);

		final List items = criteria.setCacheable(true)
				.setFirstResult(page.getStartRecord())
				.setMaxResults(page.getPageSize()).list();
		final PageSupport ps = new PageSupport(page, items, (int) recordCount);
		return ps;

	}

	/**
	 * 
	 * @param dc
	 * @param pageSize
	 * @param pageNo
	 * @return
	 */
	private PageSupport findPageByCriteria(final DetachedCriteria dc,
			final int pageSize, final int pageNo) {
		final Session session = this.getSession();
		Criteria criteria = dc.getExecutableCriteria(session);
		final OrderEntry[] orderEntries = HibernateUtil.getOrders(criteria);
		criteria = HibernateUtil.removeOrders(criteria);
		final Projection projection = HibernateUtil.getProjection(criteria);

		final Object object = criteria.setProjection(Projections.rowCount())
				.uniqueResult();

		final int recordCount = ((Long) object).intValue();

		criteria.setProjection(projection);
		if (projection == null) {
			criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
		}
		// Add the orginal orderEntries
		criteria = HibernateUtil.addOrders(criteria, orderEntries);

		int reallyPageNo = pageNo;
		final int pageCount = recordCount - 1 / pageSize + 1;

		if (reallyPageNo <= 0) {
			reallyPageNo = 0;
		}
		reallyPageNo = pageNo > pageCount ? pageCount : pageNo;
		final int startIndex = pageSize * (pageNo - 1);
		final List items = criteria.setFirstResult(startIndex)
				.setMaxResults(pageSize).list();
		final PageSupport ps = new PageSupport(items, recordCount, pageSize,
				reallyPageNo);
		return ps;

	}

	/**
	 * 返回符合条件的记录数量
	 * 
	 * @param dc
	 * @return int
	 */
	@Override
	public int getCountByCriteria(final DetachedCriteria dc) {
		final Session session = this.getSession();
		final Criteria criteria = dc.getExecutableCriteria(session);
		return Integer
				.parseInt(""
						+ criteria.setProjection(Projections.rowCount())
								.uniqueResult());

	}

	/**
	 * 统计符合条件的总数
	 * 
	 * @Description: TODO
	 * @param dc
	 * @return
	 */
	public int sumByCriteria(final DetachedCriteria dc) {
		// try{
		final Session session = this.getSession();
		final Criteria criteria = dc.getExecutableCriteria(session);
		final int sumResult = Integer
				.parseInt((criteria.uniqueResult() == null ? "0" : String
						.valueOf(criteria.uniqueResult())));
		// System.out.println(sumResult);
		return sumResult;
		// }catch (Exception e) {
		// e.printStackTrace();
		// }
		// return 0;
	}

	/**
	 * 
	 * @param sql
	 * @param c
	 * @param pageSize
	 * @param pageNo
	 * @return
	 */
	@Override
	public List findBySqlEntity(final String sql, final Class c,
			final int pageSize, final int pageNo) {
		int startIndex = pageSize * (pageNo - 1);
		if (pageNo == 0) {
			startIndex = 0;
		}
		final int startIndex1 = startIndex;
		final Session session = this.getSession();
		final SQLQuery queryObject = session.createSQLQuery(sql).addEntity(c);
		queryObject.setFirstResult(startIndex1);
		queryObject.setMaxResults(pageSize);
		return queryObject.list();
	}

}
